// Copyright 2017 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
当然，以下是`CPDF_CMap`类中各个函数和成员变量的功能概述：

### 公有成员函数(Public Member Functions)

1. * *`static constexpr size_t kDirectMapTableSize = 65536;`* *
-定义直接映射表的大小为65536（2 ^ 16），用于存储字符码到CID的直接映射。

2. * *`bool IsLoaded() const { return m_bLoaded; }`* *
-检查CMap是否已加载。返回布尔值，`true`表示已加载，`false`表示未加载。

3. * *`bool IsVertWriting() const { return m_bVertical; }`* *
-检查CMap是否用于垂直书写。返回布尔值，`true`表示是垂直书写，`false`表示是水平书写。

4. * *`uint16_t CIDFromCharCode(uint32_t charcode) const;`* *
-根据提供的字符码（charcode）查找对应的CID（字符标识符）。返回一个16位整数，表示CID。

5. * *`int GetCharSize(uint32_t charcode) const;`* *
-获取指定字符码（charcode）的字节数。返回一个整数，表示字符的字节长度。

6. * *`uint32_t GetNextChar(ByteStringView pString, size_t * pOffset) const;`* *
-从给定的字符串中提取下一个字符，并更新偏移量。返回一个32位整数，表示提取的字符码。

7. * *`size_t CountChar(ByteStringView pString) const;`* *
-计算给定字符串中的字符数量。返回一个大小为`size_t`的整数，表示字符的数量。

8. * *`void AppendChar(ByteString * str, uint32_t charcode) const;`* *
-将指定字符码（charcode）追加到给定的字符串中。`str`是一个指向`ByteString`对象的指针，`charcode`是要追加的字符码。

9. * *`void SetVertical(bool vert) { m_bVertical = vert; }`* *
-设置CMap是否用于垂直书写。`vert`是一个布尔值，`true`表示垂直书写，`false`表示水平书写。

10. * *`void SetCodingScheme(CodingScheme scheme) { m_CodingScheme = scheme; }`* *
-设置CMap的编码方案。`scheme`是一个枚举类型`CodingScheme`，表示编码方案的类型。

11. * *`void SetAdditionalMappings(std::vector<CIDRange> mappings);`* *
-设置额外的字符码到CID的映射。`mappings`是一个包含`CIDRange`对象的向量，每个`CIDRange`定义了一组字符码范围及其对应的CID。

12. * *`void SetMixedFourByteLeadingRanges(std::vector<CodeRange> ranges);`* *
-设置混合四字节前导范围。`ranges`是一个包含`CodeRange`对象的向量，每个`CodeRange`定义了一组字符码范围。

13. * *`CIDCoding GetCoding() const { return m_Coding; }`* *
-获取CMap的编码方式。返回一个`CIDCoding`枚举值，表示编码方式的类型。

14. * *`const fxcmap::CMap * GetEmbedMap() const { return m_pEmbedMap; }`* *
-获取嵌入的CMap对象。返回一个指向`fxcmap::CMap`对象的常量指针。

15. * *`CIDSet GetCharset() const { return m_Charset; }`* *
-获取CMap的字符集。返回一个`CIDSet`枚举值，表示字符集的类型。

16. * *`void SetCharset(CIDSet set) { m_Charset = set; }`* *
-设置CMap的字符集。`set`是一个`CIDSet`枚举值，表示字符集的类型。

17. * *`void SetDirectCharcodeToCIDTableRange(uint32_t start_code, uint32_t end_code, uint16_t start_cid);`* *
-设置直接字符码到CID的映射范围。`start_code`和`end_code`分别表示字符码范围的起始和结束值，`start_cid`表示起始CID。

18. * *`bool IsDirectCharcodeToCIDTableIsEmpty() const { return m_DirectCharcodeToCIDTable.empty(); }`* *
-检查直接字符码到CID的映射表是否为空。返回布尔值，`true`表示为空，`false`表示不为空。

### 构造函数和析构函数

1. * *`explicit CPDF_CMap(ByteStringView bsPredefinedName);`* *
-构造函数：使用预定义名称初始化`CPDF_CMap`实例。`bsPredefinedName`是一个`ByteStringView`类型的参数，表示预定义的CMap名称。

2. * *`explicit CPDF_CMap(pdfium::span<const uint8_t> spEmbeddedData);`* *
-构造函数：使用嵌入的数据初始化`CPDF_CMap`实例。`spEmbeddedData`是一个`pdfium::span<const uint8_t>`类型的参数，表示嵌入的CMap数据。

3. * *`~CPDF_CMap() override;`* *
-析构函数：清理`CPDF_CMap`实例所占用的资源。

### 私有成员变量(Private Member Variables)

1. * *`bool m_bLoaded = false;`* *
-标记CMap是否已加载。默认值为`false`，表示尚未加载。

2. * *`bool m_bVertical = false;`* *
-标记CMap是否用于垂直书写。默认值为`false`，表示水平书写。

3. * *`CIDSet m_Charset = CIDSET_UNKNOWN;`* *
-存储CMap的字符集。默认值为`CIDSET_UNKNOWN`，表示未知字符集。

4. * *`CodingScheme m_CodingScheme = TwoBytes;`* *
-存储CMap的编码方案。默认值为`TwoBytes`，表示双字节编码。

5. * *`CIDCoding m_Coding = CIDCoding::kUNKNOWN;`* *
-存储CMap的编码方式。默认值为`CIDCoding::kUNKNOWN`，表示未知编码方式。

6. * *`std::vector<bool> m_MixedTwoByteLeadingBytes;`* *
-存储混合双字节前导字节的布尔向量。用于处理混合编码方案。

7. * *`std::vector<CodeRange> m_MixedFourByteLeadingRanges;`* *
-存储混合四字节前导范围的向量。每个`CodeRange`对象定义了一组字符码范围。

8. * *`FixedSizeDataVector<uint16_t > m_DirectCharcodeToCIDTable;`* *
-存储直接字符码到CID的映射表。使用`FixedSizeDataVector`来管理固定大小的数据向量。

9. * *`std::vector<CIDRange> m_AdditionalCharcodeToCIDMappings;`* *
-存储额外的字符码到CID的映射向量。每个`CIDRange`对象定义了一组字符码范围及其对应的CID。

10. * *`UnownedPtr<const fxcmap::CMap > m_pEmbedMap;`* *
-存储嵌入的CMap对象的非拥有指针。用于访问嵌入的CMap数据。

### 功能概述

`CPDF_CMap`类用于管理和解析PDF文档中的CMap（字符映射表）。CMap用于将字符编码转换为CID（字符标识符），从而实现字符的正确显示和渲染。`CPDF_CMap`类提供了以下功能：

- **字符码到CID的映射 * *：通过`CIDFromCharCode`方法将字符码转换为CID。
- **字符编码和解码 * *：提供获取字符大小、提取字符、计算字符数量等功能。
- **编码方案和字符集 * *：支持多种编码方案和字符集，如GB、BIG5、JIS、KOREA等。
- **垂直书写支持 * *：支持垂直书写的CMap，适用于某些亚洲语言的排版需求。
- **嵌入CMap数据 * *：可以加载预定义的CMap或嵌入的CMap数据。
- **缓存和优化 * *：使用直接映射表和额外映射表来提高字符码到CID的转换效率。

这些函数和成员变量共同工作，以实现对PDF文档中CMap的高效管理和解析，确保字符的正确显示和渲染。
#ifndef CORE_FPDFAPI_FONT_CPDF_CMAP_H_
#define CORE_FPDFAPI_FONT_CPDF_CMAP_H_

#include <stdint.h>

#include <array>
#include <vector>

#include "core/fpdfapi/font/cpdf_cidfont.h"
#include "core/fxcrt/fixed_size_data_vector.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/span.h"
#include "core/fxcrt/unowned_ptr.h"

namespace fxcmap {
struct CMap;
}

enum class CIDCoding : uint8_t {
  kUNKNOWN = 0,
  kGB,
  kBIG5,
  kJIS,
  kKOREA,
  kUCS2,
  kCID,
  kUTF16,
};

class CPDF_CMap final : public Retainable {
 public:
  static constexpr size_t kDirectMapTableSize = 65536;

  enum CodingScheme : uint8_t {
    OneByte,
    TwoBytes,
    MixedTwoBytes,
    MixedFourBytes
  };

  struct CodeRange {
    size_t m_CharSize;
    std::array<uint8_t, 4> m_Lower;
    std::array<uint8_t, 4> m_Upper;
  };

  struct CIDRange {
    uint32_t m_StartCode;
    uint32_t m_EndCode;
    uint16_t m_StartCID;
  };

  CONSTRUCT_VIA_MAKE_RETAIN;

  bool IsLoaded() const { return m_bLoaded; }
  bool IsVertWriting() const { return m_bVertical; }

  uint16_t CIDFromCharCode(uint32_t charcode) const;

  int GetCharSize(uint32_t charcode) const;
  uint32_t GetNextChar(ByteStringView pString, size_t* pOffset) const;
  size_t CountChar(ByteStringView pString) const;
  void AppendChar(ByteString* str, uint32_t charcode) const;

  void SetVertical(bool vert) { m_bVertical = vert; }
  void SetCodingScheme(CodingScheme scheme) { m_CodingScheme = scheme; }
  void SetAdditionalMappings(std::vector<CIDRange> mappings);
  void SetMixedFourByteLeadingRanges(std::vector<CodeRange> ranges);

  CIDCoding GetCoding() const { return m_Coding; }
  const fxcmap::CMap* GetEmbedMap() const { return m_pEmbedMap; }
  CIDSet GetCharset() const { return m_Charset; }
  void SetCharset(CIDSet set) { m_Charset = set; }

  void SetDirectCharcodeToCIDTableRange(uint32_t start_code,
                                        uint32_t end_code,
                                        uint16_t start_cid);
  bool IsDirectCharcodeToCIDTableIsEmpty() const {
    return m_DirectCharcodeToCIDTable.empty();
  }

 private:
  explicit CPDF_CMap(ByteStringView bsPredefinedName);
  explicit CPDF_CMap(pdfium::span<const uint8_t> spEmbeddedData);
  ~CPDF_CMap() override;

  bool m_bLoaded = false;
  bool m_bVertical = false;
  CIDSet m_Charset = CIDSET_UNKNOWN;
  CodingScheme m_CodingScheme = TwoBytes;
  CIDCoding m_Coding = CIDCoding::kUNKNOWN;
  std::vector<bool> m_MixedTwoByteLeadingBytes;
  std::vector<CodeRange> m_MixedFourByteLeadingRanges;
  FixedSizeDataVector<uint16_t> m_DirectCharcodeToCIDTable;
  std::vector<CIDRange> m_AdditionalCharcodeToCIDMappings;
  UnownedPtr<const fxcmap::CMap> m_pEmbedMap;
};

#endif  // CORE_FPDFAPI_FONT_CPDF_CMAP_H_
